﻿using ArtMath.Attribute;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Data;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.ComponentModel;

namespace ArtMath.Component.Vector
{
    /// <summary>
    /// 向量加法
    /// </summary>
    [Serializable]
    public class TwoVectorsAddition : VectorBase
    {
        VectorBase v1, v2;
        bool unlimit;
        public TwoVectorsAddition(SketchPad pad, string name, VectorBase v1, VectorBase v2, bool addToList = true) : base(pad, name, ToolTypeName.xljf, addToList)
        {
            AllowFix = false;
            AddVector1 = v1;
            AddVector2 = v2;
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}1", "AddendVector"), TypeConverter(typeof(ExpandableObjectConverter))]
        public VectorBase AddVector1
        {
            get { return v1; }
            set
            {
                v1?.OutChildren_Line.Remove(this);
                v1 = value;
                v1?.OutChildren_Line.Add(this);
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}2", "AddendVector"), TypeConverter(typeof(ExpandableObjectConverter))]
        public VectorBase AddVector2
        {
            get { return v2; }
            set
            {
                v2?.OutChildren_Line.Remove(this);
                v2 = value;
                v2?.OutChildren_Line.Add(this);
            }
        }
        [MultilingualCategory("Parameter"), ReadOnly(true)]
        public override PointBase Point2
        {
            get
            {
                return base.Point2;
            }

            set
            {
                base.Point2 = value;
            }
        }
        public override double NewSlope
        {
            get
            {
                PointD newVec = AddVector1.Point2.NewXY - AddVector1.Point1.NewXY + AddVector2.Point2.NewXY - AddVector2.Point1.NewXY;
                return newVec.Y / newVec.X;
            }
        }
        public override double NewPSlope
        {
            get
            {
                PointD newVec = AddVector1.Point2.NewPxy - AddVector1.Point1.NewPxy + AddVector2.Point2.NewPxy - AddVector2.Point1.NewPxy;
                return newVec.Y / newVec.X;
            }
        }
        public override bool PointsHaveConstraint
        {
            get { return true; }
        }
        [Browsable(false)]
        public override AngleStringX RotateAngle
        {
            get
            {
                return base.RotateAngle;
            }

            set
            {
                base.RotateAngle = value;
            }
        }
        [Browsable(false)]
        public override RPointS RotateCenter
        {
            get
            {
                return base.RotateCenter;
            }

            set
            {
                base.RotateCenter = value;
            }
        }
        public override int ClickTimes
        {
            get
            {
                return 1;
            }
        }
        protected override void PointMoving_AsOutChildrenLimit(PointBase movePoint)
        {
            int movcnt = CountMovablePoints();
            switch (movcnt)
            {
                case 0:
                    throw new PointMovingException(this, OfTranslator2(Resources.JoinLocalizedString("EndPoint", "CannotMove")));
                case 1:
                case 2:
                    PointBase fix, move;
                    PointD tmp = AddVector1.Point2.NewPxy - AddVector1.Point1.NewPxy + AddVector2.Point2.NewPxy - AddVector2.Point1.NewPxy;
                    if (Point2.Movable)
                    {
                        move = Point2;
                        fix = Point1;
                        tmp += fix.NewPxy;
                    }
                    else
                    {
                        move = Point1;
                        fix = Point2;
                        tmp = fix.NewPxy - tmp;
                    }
                    unlimit = fix.TempMoveLock = true;
                    try
                    {
                        move.Move(tmp);
                    }
                    finally
                    {
                        unlimit = fix.TempMoveLock = false;
                    }
                    break;
            }
        }
        public override PointCollectionBase[] GetInPointMovingRange(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 1:
                    if (unlimit)
                    {
                        return Universal.GenerateInstanceArray();
                    }
                    else
                    {
                        PointD tmp = AddVector1.Point2.NewXY - AddVector1.Point1.NewXY + AddVector2.Point2.NewXY - AddVector2.Point1.NewXY;
                        return new PointCollectionBase[] { new DiscontinuityPoint(movePoint == Point1 ? Point2.NewXY - tmp : Point1.NewXY + tmp) };
                    }
            }
            return base.GetInPointMovingRange(movePoint, sender);
        }
        public override void CreateComponents()
        {
            Point1 = Pad.CreatePoint(Resources.Translate("StartPoint"), SpareCoordinate_);
            Point2 = Pad.CreatePoint(Resources.Translate("TerminalPoint"), AddVector1.Point2.Pxy - AddVector1.Point1.Pxy + AddVector2.Point2.Pxy - AddVector2.Point1.Pxy + Point1.Pxy, false);
            base.CreateComponents();
        }
    }
}
